package com.edushare.common.backup;

import org.apache.cayenne.access.DataContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import com.edushare.common.constants.ConfigPropertyName;
import com.edushare.common.dao.ConfigPropertiesDAO;
import com.edushare.common.dao.SystemBackupDAO;
import com.edushare.common.exceptions.ProcessingException;
import com.edushare.common.orm.CayenneORMInterface;
import com.edushare.common.vo.ConfigProperties;
import com.edushare.common.vo.SystemBackup;

public class BackupProcessThread implements Runnable {
	
	private static Log log = LogFactory.getLog(BackupProcessThread.class);
	private DataContext dataContext;
	private CayenneORMInterface ormInterface;
	private SystemBackup sytemBackup;
	
	public BackupProcessThread(SystemBackup bkp) throws ProcessingException{
		log.warn("============== STARTING BACKUP PROCESS ===============");
		this.dataContext = DataContext.createDataContext();
		this.ormInterface = new CayenneORMInterface();
		ormInterface.setDataContext(dataContext);
//		this.sytemBackup = bkp;
		this.sytemBackup = new SystemBackupDAO(ormInterface).getSystemBackupById(bkp.getSystemBackupId());
			
		int currentStatus = new ConfigPropertiesDAO(ormInterface).getBackupStatus();
		if(currentStatus!=ConfigProperties.SYSTEM_BACKUP_STATUS_FAILED && 
				currentStatus!=ConfigProperties.SYSTEM_BACKUP_STATUS_OK){
			throw new ProcessingException("Cannot start backup process becasue one is already running.");
		}
	}
	
	public void run() {
		log.warn("============== STARTING BACKUP THREAD ===============");
		log.warn("============== BACKUP DETAILS: [id="+ this.sytemBackup.getSystemBackupId()+", type="+ sytemBackup.getBackupType() +"] ===============");
		try{
			switch(this.sytemBackup.getBackupType()){
			
			case SystemBackup.BACKUP_TYPE_DB_ONLY:
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_DB);
				SystemBackupUtils.backupDB(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_CONFIG);
				BackupConfigFileProcessor.createBackupConfigFile(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_OK);
				break;
			case SystemBackup.BACKUP_TYPE_MEDIA_ONLY:
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_MEDIA);
				SystemBackupUtils.backupMedia(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_CONFIG);
				BackupConfigFileProcessor.createBackupConfigFile(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_OK);
				break;
			case SystemBackup.BACKUP_TYPE_COMPLETE: 
				 default:
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_DB);
				SystemBackupUtils.backupDB(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_MEDIA);
				SystemBackupUtils.backupMedia(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_PROCESSING_CONFIG);
				BackupConfigFileProcessor.createBackupConfigFile(sytemBackup);
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_OK);
				break;
				
			}
		}catch(Exception e){
			try{
				setStatus(ConfigProperties.SYSTEM_BACKUP_STATUS_FAILED);
				log.fatal("******* UNABLE TO COMPLETE SYSTEM BACKUP  ********", e);
			}catch(Exception e1){
				log.fatal("******* UNABLE TO COMPLETE SYSTEM BACKUP OR SET STATUS  ********", e1);
			}
		}
	}

	private void setStatus(int systemBackupStatus) {
		ConfigProperties prop = new ConfigPropertiesDAO(ormInterface).getConfigProperty(ConfigPropertyName.SYSTEM_BACKUP_STATUS, false);
		sytemBackup.setBackupStatus(systemBackupStatus);
		prop.setValue(""+ systemBackupStatus);
		dataContext.commitChanges();
	}

}
